package com.nondo.rdp.finance.task.service.impl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import net.sf.json.JSONArray;
import net.sf.json.JSONObject;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

import com.nondo.rdp.auth.common.DateUtils;
import com.nondo.rdp.auth.domain.User;
import com.nondo.rdp.finance.domain.analysis.Analysis;
import com.nondo.rdp.finance.service.SettingService;
import com.nondo.rdp.finance.service.analysis.AnalysisService;
import com.nondo.rdp.finance.task.param.WallStreetParam;
import com.nondo.rdp.finance.task.result.WallStreetResult;
import com.nondo.rdp.finance.task.service.ICrawlerService;
import com.nondo.rdp.finance.task.util.TaskConstant;

/**
 * 爬虫服务实现类
 * 
 * @author nondo
 *
 */
@Component
public class CrawlerServiceImpl implements ICrawlerService {

	private static final Logger Logger = LoggerFactory
			.getLogger(CrawlerServiceImpl.class);

	@SuppressWarnings("rawtypes")
	@Autowired
	RedisTemplate redisTemplate;
	
	@Autowired
	RestTemplate restTemplate;
	
	@Autowired
	SettingService settingService;
	
	@Autowired
	AnalysisService analysisService;
	
	/**
	 * 设置互斥锁
	 * @param key
	 * @param expire
	 * @return 是否正在运行当中
	 */
	private boolean getMutexLock(String key, int expire) {
		try {
			// 延迟一下避免时钟同步造成的竞争
			double delay = Math.random() * 1000;
			Thread.sleep(new Double(delay).longValue());
		} catch (InterruptedException e) {
			Logger.error("【定时任务线程休眠异常中断】");
		}
		@SuppressWarnings("unchecked")
		ValueOperations<String, Boolean> operation = redisTemplate.opsForValue();
 		Boolean isRun = operation.get(TaskConstant.LOCK_PREFIX + key);
		if (isRun != null && isRun == true) {
			return true;
		} else {
			operation.set(TaskConstant.LOCK_PREFIX + key, true, expire, TimeUnit.SECONDS);
		}
		return false;
	}
	
	/**
	 * 抓取华尔街见闻A股快讯
	 */
	@Override
	@Scheduled(cron = "0 0/2 * * * ?")
	public void crawlWSNews() {
		//定时任务关闭状态
		if (settingService.judgeTaskStatus())
			return ;
		// 分布式环境下互斥访问
		String key = "crawlWSNews";
		int expire = 1 * 60;
		if (getMutexLock(key, expire))
			return ;
		
		//对华尔街见闻发起网络请求
		WallStreetParam wsParam = new WallStreetParam();
		long cursor = System.currentTimeMillis()/1000;
		wsParam.setCursor(cursor);	
		Map<String,Object> requestParam = new HashMap<String,Object>();
		requestParam.put("channel", wsParam.getChannel());
		requestParam.put("client", wsParam.getClient());
		requestParam.put("cursor", wsParam.getCursor());
		requestParam.put("limit", wsParam.getLimit());
		String result = restTemplate.getForObject(TaskConstant.URL_WALL_STREET_NEWS, String.class, requestParam);
		
		//解析返回数据
		JSONObject jsonObj = JSONObject.fromObject(result);
		Integer jsonCode = jsonObj.getInt("code");
		if (jsonCode != 20000) {
			Logger.error("【抓取华尔街见闻A股快讯失败：】" + jsonObj.getString("message"));
			return ;
		}
		JSONObject jsonData = jsonObj.getJSONObject("data");
		JSONArray jsonItems = jsonData.getJSONArray("items");
		List<WallStreetResult> wsResultList = new ArrayList<WallStreetResult>();
		for (int i = 0; i < jsonItems.size(); i++) {
			WallStreetResult wsResult = new WallStreetResult();
			JSONObject jsonItem = jsonItems.getJSONObject(i);
			wsResult.setId(jsonItem.getLong("id"));
			wsResult.setContent(jsonItem.getString("content"));
			wsResultList.add(wsResult);
		}
		//调用接口入库--可以另开线程处理
		int num = 0;
		for (WallStreetResult wsResult : wsResultList) {
			Analysis analysis = new Analysis();
			Long wsId = wsResult.getId();
			analysis.setWsId(wsId);
			// 判断是否已采集过
			Analysis analysisDb = analysisService.findByWsId(wsId);
			if (analysisDb != null) {
				continue ;
			}
			String content = wsResult.getContent();
			content = content.replaceAll("<.*?>", "");
			if (content.length() > 32) {
				analysis.setTitle(content.substring(0, 28) + "...");
			} else {
				analysis.setTitle(content);
			}
			analysis.setBody(content);
			analysis.setType(4);// 金融快讯
			User user = new User();
			user.setId(1L);// 设置用户
			analysis.setUser(user);
			analysis = analysisService.save(analysis);
			if (analysis == null) {
				Logger.error("【抓取华尔街见闻A股快讯调用接口入库失败：wsId=】" + wsId);
				continue ;
			}
			num++;// 实际入库条数
		}
		
		System.out.println(DateUtils.getDateTime() + "【本次抓取华尔街见闻A股快讯共" + wsResultList.size() + "条,实际入库" + num + "条】");
	}

}
